home *** CD-ROM | disk | FTP | other *** search
- /*
- * This file is part of ixemul.library for the Amiga.
- * Copyright (C) 1991, 1992 Markus M. Wild
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- #define _KERNEL
- #include "ixemul.h"
- #include "kprintf.h"
-
- /* this one is for Mike B. Smith ;-) */
-
- void set_dir_name_from_lock(BPTR lock)
- {
- char *buf = (char *) kmalloc (MAXPATHLEN);
-
- if (buf)
- {
- /* NOTE: This shortcuts any symlinks. But then, Unix does the
- * same, and a shell that wants to be smart about symlinks,
- * has to track chdir()s itself as well */
- if (NameFromLock (lock, buf, MAXPATHLEN))
- SetCurrentDirName (buf);
- kfree (buf);
- }
- }
-
- /*
- * Checks if pathname "name1" is above
- * "name" in directory structure.
- * Lock()/Unlock() are used instead of __lock/__unlock
- * because this routine seems to loop if name2 is a subdir of name1
- */
- static short
- dirisparent (char *name1, char *name2) {
- short ret = 0;
- BPTR lock1;
-
- lock1 = Lock (name1, SHARED_LOCK);
- if (lock1) {
- BPTR lock2;
-
- lock2 = Lock (name2, SHARED_LOCK);
- if (lock2) {
-
- switch (SameLock (lock1, lock2)) {
-
- case LOCK_DIFFERENT:
- break;
-
- case LOCK_SAME:
- ret = 2;
- break;
-
- case LOCK_SAME_VOLUME:
- {
- BPTR l;
-
- while (lock2) {
- l = lock2;
- lock2 = ParentDir (l);
- UnLock (l);
- if (SameLock (lock1, lock2) == LOCK_SAME) {
- ret = 1;
- break;
- }
- }
- break;
- }
- }
- UnLock (lock2);
- }
- UnLock (lock1);
- }
- return ret;
- }
-
- /* if we change our directory, we have to remember the original cd, when
- * the process was started, because we're not allowed to unlock this
- * lock, since we didn't obtain it. */
-
- int chdir (char *path)
- {
- BPTR oldlock, newlock;
- int error = 0;
- int omask;
- struct stat stb;
- /* Sigh... CurrentDir() is a DOS-library function, it would probably be
- * ok to just use pr_CurrentDir, but alas, this way we're conformant to
- * programming style guidelines, but we pay the overhead of locking dosbase
- */
-
- /* chdir("/") with u.u_root_directory set, chdir's to root directory */
- if (!strcmp("/",path) && *u.u_root_directory)
- path = u.u_root_directory;
-
- if (syscall (SYS_stat, path, &stb) == 0 && !(stb.st_mode&S_IFDIR))
- {
- errno = ENOTDIR;
- KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
- return -1;
- }
-
- omask = syscall (SYS_sigsetmask, ~0);
-
- newlock = __lock (path, ACCESS_READ);
-
- if (newlock == NULL && IoErr() == 6262)
- {
- u.u_is_root = 1;
- SetCurrentDirName("/");
- syscall (SYS_sigsetmask, omask);
- return 0;
- }
- else if (newlock)
- {
- /* chroot() support - don't do a chdir if the path
- * is a parent directory of the root directory
- */
- if (*u.u_root_directory) {
- char dir[MAXPATHLEN];
-
- if (NameFromLock (newlock, dir, MAXPATHLEN)) {
- if (dirisparent(dir,u.u_root_directory) == 1) {
- errno = EACCES;
- goto chdirerr;
- }
- }
- else {
- errno = __ioerr_to_errno (IoErr ());
- goto chdirerr;
- }
- }
-
- u.u_is_root = 0;
- oldlock = CurrentDir (newlock);
-
- if (u.u_startup_cd == (BPTR)-1)
- u.u_startup_cd = oldlock;
- else
- __unlock (oldlock);
-
- set_dir_name_from_lock(newlock);
-
- syscall (SYS_sigsetmask, omask);
- return 0;
- }
- error = __ioerr_to_errno (IoErr ());
-
- chdirerr:
- syscall (SYS_sigsetmask, omask);
- errno = error;
- KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
- return -1;
- }
-
- /* change the "root" directory to dir */
- int chroot(char *dir) {
- int retval;
-
- retval = chdir(dir);
-
- if (retval == 0) {
- BPTR rootlock = __lock(dir,ACCESS_READ);
- if (rootlock)
- NameFromLock(rootlock,u.u_root_directory,MAXPATHLEN);
- else
- retval = -1;
- __unlock(rootlock);
- }
- return retval;
- }
-